package com.caigou.task;

import com.caigou.bean.cms.entity.ArticleStatisticsDay;
import com.caigou.bean.cms.entity.Channel;
import com.caigou.bean.param.FrontChannelDataPram;
import com.caigou.component.RedisComponent;
import com.caigou.service.ArticleService;
import com.caigou.service.ChannelService;
import com.caigou.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
@EnableScheduling
public class ArticleStatisticsTask {
    @Resource
    private ArticleService articleService;
    @Resource
    private ChannelService channelService;

    @Resource
    RedisComponent redisComponent;

    @Scheduled(cron = "0 30 0 * * ?")//每天零时30分执行一次,统计每天pv排名前若干条的文章插入到t_article_statistics_day表
    //@Scheduled(cron = "*/15 * * * * ?")//每15秒执行一次
    public void articleStatisticsDay() {
        String lockKey = "task:lock:cms:articlesStatisticsDay";//文章pv日统计定时任务分布式锁，避免该任务在负载均衡的服务器中同时执行
        boolean lockFlag = redisComponent.setLock(lockKey, 3600);
        if(!lockFlag){
            log.info("文章pv日统计定时任务获取分布式锁失败，该任务已经在其他服务器节点执行");
            return;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);//获取前一天的信息
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date startTime = calendar.getTime();

        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        Date endTime = calendar.getTime();

        int limit = 1000;
        log.info("----开始统计的官网排名前{}的日pv---------{}",limit, startTime);
        List<ArticleStatisticsDay> list = articleService.queryArticleStatisticsDayByTime(startTime, endTime, limit);
        for(ArticleStatisticsDay articleStatisticsDay:list){
            java.sql.Date statisticsDay = new java.sql.Date(startTime.getTime());
            articleStatisticsDay.setStatisticsDay(statisticsDay);
            articleStatisticsDay.setCreateTime(new Date(System.currentTimeMillis()));
            int result = articleService.saveArticleStatisticsDay(articleStatisticsDay);
            log.info("统计articleId={}, statisticsDay={}, pv={},保存结果={}", articleStatisticsDay.getArticleId(), statisticsDay, articleStatisticsDay.getPv(), result);
        }
        log.info("----统计的官网排名前{}的日pv结束，共{}条---------{}", limit, list.size(), startTime);
        boolean releaseFlag = redisComponent.releaseLock(lockKey);
        log.info("释放文章pv日统计定时任务分布式锁key={}，result={}", lockKey, releaseFlag);
    }


    //@Scheduled(cron = "10 30 11 * * ?")//每天零时0分10秒执行一次,将5个行业频道\5个专业频道及网站首页的排行榜数据保存到redis
    @Scheduled(cron = "10 0 0 * * ?")//每天零时0分10秒执行一次,将5个行业频道\5个专业频道及网站首页的排行榜数据保存到redis
    //@Scheduled(cron = "*/15 * * * * ?")//每15秒执行一次
    public void articleStatisticsRank() {
        String lockKey = "task:lock:cms:articlesStatisticsRank";//文章pv排行榜定时任务分布式锁，避免该任务在负载均衡的服务器中同时执行
        boolean lockFlag = redisComponent.setLock(lockKey, 3600);
        if(!lockFlag){
            log.info("文章pv排行榜定时任务获取分布式锁失败，该任务已经在其他服务器节点执行");
            return;
        }
        log.info("====文章pv排行榜定时任务保存到redis开始=====");
        for(int plateId=101; plateId<=111; plateId++){
            if(plateId==101||(plateId>=107 && plateId<=111)) {
                Channel channel = channelService.getChannelByPlateId(plateId+"");
                FrontChannelDataPram param = new FrontChannelDataPram();
                param.setPageNum(1);
                param.setPageSize(10);
                param.setPlateId(channel.getChannelValue());
                for (int i= 1; i <= 3; i++) {
                    param.setQueryType(i);
                    //首先清除redis中排行榜缓存数据
                    boolean flag = channelService.deleteChannelHotSearchDataFromRedis(param);
                    //其次将数据库中数据保存到redis中
                    Result result = channelService.loadChannelHotSearchData(param);
                    log.info("从redis中删除排行榜数据的结果为{}, queryType={} plateId={} rank's list={}", flag, param.getQueryType(), param.getPlateId(), result.getData());
                }
            }
        }
        log.info("====文章pv排行榜定时任务保存到redis结束=====");
        boolean releaseFlag = redisComponent.releaseLock(lockKey);
        log.info("释放文章pv排行榜定时任务分布式锁key={}，result={}", lockKey, releaseFlag);
    }

    @Scheduled(cron = "10 0 3 * * ?")//每天3时0分10秒执行一次,删除t_article_statistics表中45天前的数据
    //@Scheduled(cron = "*/15 * * * * ?")//每15秒执行一次
    public void deleteArticleStatistics() {
        String lockKey = "task:lock:cms:deleteArticleStatistics";//删除文章点击历史数据的定时任务分布式锁，避免该任务在负载均衡的服务器中同时执行
        boolean lockFlag = redisComponent.setLock(lockKey, 3600);
        if(!lockFlag){
            log.info("删除文章点击历史数据的定时任务分布式锁失败，该任务已经在其他服务器节点执行");
            return;
        }
        log.info("====删除文章点击历史数据的定时任务开始=====");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -45);//获取45天前的时间
        Date historyTime = calendar.getTime();
        int result = articleService.deleteArticleStatisticsByTime(historyTime);
        log.info("删除文章点击历史数据小于{}的共{}条", historyTime, result);
        boolean releaseFlag = redisComponent.releaseLock(lockKey);
        log.info("释放删除文章点击历史数据的定时任务分布式锁key={}，result={}", lockKey, releaseFlag);
    }

}
